package cn.iocoder.yudao.module.digital.dal.mysql.cardkeysecret;

import java.time.LocalDateTime;
import java.util.*;

import cn.hutool.core.date.DateUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.digital.dal.dataobject.cardkeyproduct.CardkeyProductDO;
import cn.iocoder.yudao.module.digital.dal.dataobject.cardkeysecret.CardkeySecretDO;
import cn.iocoder.yudao.module.digital.enums.cardkeysecret.ClaimStatusEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.digital.controller.admin.cardkeysecret.vo.*;

/**
 * 卡密密钥 Mapper
 *
 * @author 超管
 */
@Mapper
public interface CardkeySecretMapper extends BaseMapperX<CardkeySecretDO> {

    default PageResult<CardkeySecretDO> selectPage(CardkeySecretPageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<CardkeySecretDO>()
                .eqIfPresent(CardkeySecretDO::getProductNo, reqVO.getProductNo())
                .eqIfPresent(CardkeySecretDO::getClaimStatus, reqVO.getClaimStatus())
                .eqIfPresent(CardkeySecretDO::getOrderNo, reqVO.getOrderNo())
                .eqIfPresent(CardkeySecretDO::getUserId, reqVO.getUserId())
                .betweenIfPresent(CardkeySecretDO::getCreateTime, reqVO.getCreateTime())
                .eqIfPresent(CardkeySecretDO::getSource, reqVO.getSource())
                .eqIfPresent(CardkeySecretDO::getRequestId, reqVO.getRequestId())
                .eqIfPresent(CardkeySecretDO::getCardAccountId, reqVO.getCardAccountId())
                .orderByDesc(CardkeySecretDO::getId));
    }

    /**
     * 查询卡密
     *
     * @param claimStatusEnum 领取状态
     * @param productNo       卡密商品编号
     * @param denomination    面额
     * @param limitSize       查询的数量
     * @return
     */
    default List<CardkeySecretDO> getCardKeySecretByProductNo(ClaimStatusEnum claimStatusEnum, String productNo,
                                                              Integer denomination, int limitSize) {
        return selectList(
                new LambdaQueryWrapperX<CardkeySecretDO>()
                        .eq(CardkeySecretDO::getProductNo, productNo)
                        .eq(CardkeySecretDO::getDenomination, denomination)
                        .eq(CardkeySecretDO::getClaimStatus, claimStatusEnum.getValue())
                        .orderByAsc(CardkeySecretDO::getCreateTime)
                        .last("LIMIT " + limitSize)
        );
    }

    /**
     * 统计卡密
     *
     * @param claimStatusEnum 领取状态
     * @param productNo       卡密商品编号
     * @param denomination    面额
     * @return
     */
    default long countCardKeySecretByProductNo(ClaimStatusEnum claimStatusEnum, String productNo, Integer denomination) {
        final LambdaQueryWrapper<CardkeySecretDO> wrapper = new LambdaQueryWrapperX<CardkeySecretDO>()
                .eq(CardkeySecretDO::getProductNo, productNo)
                .eq(CardkeySecretDO::getDenomination, denomination)
                .eq(CardkeySecretDO::getClaimStatus, claimStatusEnum.getValue())
                .orderByAsc(CardkeySecretDO::getCreateTime);
        return selectCount(wrapper);
    }

    default List<CardkeySecretDO> getCardKeySecretByOrderNo(String orderNo) {
        return selectList(
                new LambdaQueryWrapperX<CardkeySecretDO>()
                        .eq(CardkeySecretDO::getOrderNo, orderNo)
                        .eq(CardkeySecretDO::getClaimStatus, ClaimStatusEnum.YES.getValue()));
    }

    default List<CardkeySecretDO> getCardKeySecretByOrderNo(Long userId, String orderNo) {
        return selectList(
                new LambdaQueryWrapperX<CardkeySecretDO>()
                        .eq(CardkeySecretDO::getOrderNo, orderNo)
                        .eq(CardkeySecretDO::getUserId, userId)
                        .eq(CardkeySecretDO::getClaimStatus, ClaimStatusEnum.YES.getValue()));
    }

    /**
     * 扣减密钥
     *
     * @param userId
     * @param orderNo
     * @param secretIds
     */
    default void deductionSecret(Long userId, String orderNo, Collection<String> secretIds) {
        for (String secretId : secretIds) {
            final CardkeySecretDO secretDO = new CardkeySecretDO();
            secretDO.setUserId(userId);
            secretDO.setOrderNo(orderNo);
            secretDO.setClaimStatus(ClaimStatusEnum.YES.getValue());
            secretDO.setClaimDate(LocalDateTime.now());

            final LambdaUpdateWrapper<CardkeySecretDO> wrapper = Wrappers.lambdaUpdate();
            wrapper.eq(CardkeySecretDO::getId, secretId);
            wrapper.eq(CardkeySecretDO::getClaimStatus, ClaimStatusEnum.NO.getValue());
            final int affectedRows = update(secretDO, wrapper);
            if (affectedRows != 1) {
                throw new RuntimeException(String.format("更新失败, userId = %s, orderNo = %s, secretId = %s", userId, orderNo, secretId));
            }
        }
    }

    default CardkeySecretDO getCardKeySecretByNumberCodePin(ClaimStatusEnum claimStatusEnum, String cardNumber, String code, String pin) {
        return selectOne(new LambdaQueryWrapperX<CardkeySecretDO>()
                .eq(CardkeySecretDO::getClaimStatus, claimStatusEnum.getValue())
                .eq(CardkeySecretDO::getCardNumber, cardNumber)
                .eq(CardkeySecretDO::getCode, code)
                .eq(CardkeySecretDO::getPin, pin));
    }

    default Long getStock(String productNo) {
        // 查询productNo对应的库存
        final Long count = selectCount(new LambdaQueryWrapperX<CardkeySecretDO>()
                .eq(CardkeySecretDO::getProductNo, productNo)
                .eq(CardkeySecretDO::getClaimStatus, ClaimStatusEnum.NO.getValue()));
        return count;
    }

}